﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using HiSport.Core.Entity;
using HiSport.Core.Util;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using System.ComponentModel;
using HiSport.Core;
using Mapster;
using HiSport.Application.HiSportService.Bas.BasSiteManagement.Dtos;
using HiSport.Core.Entity.HiSportEntity.Bas;
using HiSport.Application.HiSportService.Bas.BasDtos;

namespace HiSport.Application.HiSportService.Bas.BasSiteManagement.Service
{
    /// <summary>
    /// 场地管理
    /// </summary>
    //[ApiDescriptionSettings("基础资料", Tag = "场地管理", SplitCamelCase = false)]
    [ApiDescriptionSettings("VenueSetup", Tag = "SiteSettings", SplitCamelCase = false)]
    public class BasSiteService : ITransient, IBasSiteService, IDynamicApiController
    {

        /// <summary>
        /// 场地类型
        /// </summary>
        private readonly SqlSugarRepository<BasSiteType> _basSiteTypeRep;
        /// <summary>
        /// 机构
        /// </summary>
        private readonly SqlSugarRepository<SysOrg> _sysOrgRep;

        /// <summary>
        /// 场地
        /// </summary>
        private readonly SqlSugarRepository<BasSite> _basSiteRep;

        /// <summary>
        /// 场馆
        /// </summary>
        private readonly SqlSugarRepository<BasVenues> _basVenuesRep;

        ///// <summary>
        ///// 运动项目类型
        ///// </summary>
        //private readonly SqlSugarRepository<BasSportsEventsType> _sportEventsTypeRep;

        public BasSiteService(
            SqlSugarRepository<BasSiteType> basSiteTypeRep,
            SqlSugarRepository<SysOrg> sysOrgRep,
            SqlSugarRepository<BasSite> basSiteRep,
            SqlSugarRepository<BasVenues> basVenuesRep
            )
        {
            _basSiteTypeRep = basSiteTypeRep;
            _sysOrgRep = sysOrgRep;
            _basSiteRep = basSiteRep;
            _basVenuesRep = basVenuesRep;
        }

        /// <summary>
        /// 创建场地
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "Create"), HttpPost]
        [DisplayName("创建场地")]
        public async Task<long> Create(BasSiteCreateUpdateInputDto input)
        {
            #region 验证参数

            await CheckParam(input);

            #endregion

            #region 业务逻辑验证

            /* 场地编码：租户内唯一，必填场地名称：租户内唯一，必填  */

            var isAnyName = await _basSiteRep.IsAnyAsync(a => a.SiteName == input.SiteName&&a.SiteTypeId==input.SiteTypeId);
            if (isAnyName)
            {
                throw Oops.Oh("已经存在此场地名称");
            }
            var isAnyCode = await _basSiteRep.IsAnyAsync(a => a.SiteCode == input.SiteCode);
            if (isAnyCode)
            {
                throw Oops.Oh("已经存在此场地编码");
            }
            #endregion

            #region 保存           
            input.Id = 0;//创建的时候ID必须=0
            var newOrg = await _basSiteRep.AsInsertable(input.Adapt<BasSite>()).ExecuteReturnEntityAsync();
            return newOrg.Id;
            #endregion
        }


        /// <summary>
        /// 修改场地
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "Update")]
        [DisplayName("修改场地")]
        public async Task Update(BasSiteCreateUpdateInputDto input)
        {
            #region 验证参数

            await CheckParam(input);

            #endregion

            #region 业务逻辑验证

            //是否存在当前ID的场地类型
            var id = input.Id;
            var data = await GetSite(id);
            #region 业务逻辑验证

            /*
             场地编码：租户内唯一，必填
场地名称：租户内唯一，必填

             */

            var isAnyName = await _basSiteRep.IsAnyAsync(a => a.SiteName == input.SiteName && a.Id != id&& a.SiteTypeId == input.SiteTypeId);
            if (isAnyName)
            {
                throw Oops.Oh("已经存在此场地名称");
            }
            var isAnyCode = await _basSiteRep.IsAnyAsync(a => a.SiteCode == input.SiteCode && a.Id != id);
            if (isAnyCode)
            {
                throw Oops.Oh("已经存在此场地编码");
            }
            #endregion

            #endregion

            #region 修改           

            await _basSiteRep.AsUpdateable(input.Adapt<BasSite>()).IgnoreColumns(true).ExecuteCommandAsync();

            #endregion

        }


        /// <summary>
        /// 查询单个场地
        /// </summary>
        /// <param name="id">场地ID</param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "Get"), HttpGet]
        [DisplayName("查询单个场地")]
        public async Task<BasSiteBasicDto> Get(long id)
        {
            var data = await GetSite(id);
            var result = data.Adapt<BasSiteBasicDto>();

            //映射
            await SiteTypeMap(new List<BasSiteBasicDto> { result });
            return result;

        }



        /// <summary>
        /// 查询场地列表 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "GetListPage"), HttpPost]
        [DisplayName("查询场地列表")]
        public async Task<SqlSugarPagedList<BasSiteBasicDto>> GetListPage(BasSiteInputDto input)
        {
            ParamNull(input);

            //TODO:采用连表查询
            //            var dictData = _basSiteRep.AsQueryable()
            // .InnerJoin<SysOrg>((a, b) => a.OrgId == b.Id)  //机构
            //   .InnerJoin<BasVenues>((a, b) => a.VenuesId == b.Id)  //场馆
            //     .InnerJoin<BasSiteType>((a, b) => a.SiteTypId == b.Id)  //场

            // .Where((a, b) => a.IsDelete == false)
            //.Select((a, b) => a)
            //.ToList();

            var data = SqlWhere(input);
            if (data == null) return new SqlSugarPagedList<BasSiteBasicDto>();

            //排序 分页
            var result = await data.OrderBuilder(input)
                .Select(x => new BasSiteBasicDto()
                {
                    Id = x.Id.SelectAll(),
                })
                .ToPagedListAsync(input.Page, input.PageSize);

            //冗余字段赋值
            await SiteTypeMap(result.Items.ToList());
            return result;
        }

        /// <summary>
        /// 删除场地
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        [ApiDescriptionSettings(Name = "Delete"), HttpDelete]
        [DisplayName("删除场地")]
        public async Task Delete(DeleteInputDto input)
        {
            ParamNull(input);

            //是否存在当前ID的场地类型
            var id = input.Id;
            var data = await GetSite(id);

            await _basSiteRep.FakeDeleteAsync(data);

        }

        #region 其余私有方法

        /// <summary>
        /// 查询场地类型
        /// </summary>
        private async Task<BasSite> GetSite(long id)
        {
            //是否存在当前ID的场地

            var data = await _basSiteRep.GetFirstAsync(a => a.IsDelete == false && a.Id == id);
            if (data == null)
            {
                throw Oops.Oh("未查询到当前场地数据");
            }
            return data;
        }

        /// <summary>
        /// 验证参数
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task CheckParam(BasSiteCreateUpdateInputDto input)
        {

            #region 验证参数

            if (input == null) throw Oops.Oh("参数错误:参数为NULL");
            var siteName = input.SiteName;
            if (string.IsNullOrWhiteSpace(siteName))
            {
                throw Oops.Oh("参数错误:场地名称不能为空");
            }

            var siteCode = input.SiteCode;
            if (string.IsNullOrWhiteSpace(siteCode))
            {
                throw Oops.Oh("参数错误:场地编码不能为空");
            }

            //机构必填
            var orgId = input.OrgId;
            if (orgId <= 0) throw Oops.Oh("参数错误:机构必填");
            var orgData = await _sysOrgRep.GetFirstAsync(a => a.IsDelete == false && a.Id == orgId);
            if (orgData == null) throw Oops.Oh("机构不存在");

            #endregion


        }

        /// <summary>
        /// 查询列表Where条件拼装
        /// 要验证返回NULL的情况
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private ISugarQueryable<BasSite> SqlWhere(BasSiteInputDto input)
        {
            if (input == null) throw Oops.Oh("参数有误:参数为NULL");
            var data = _basSiteRep.AsQueryable();

            data = data.Where(a => a.IsDelete == false);

            #region 机构
            var orgIds = input.OrgIds;
            if (!orgIds.IsNullOrEmpty() && orgIds.Any())
            {
                data = data.Where(a => orgIds.Contains(a.OrgId));
            }
            #endregion

            #region 场管列表查询
            var basVenuesIdList = input.VenuesIdList;
            if (basVenuesIdList != null && basVenuesIdList.Count > 0)
            {
                data = data.Where(a => basVenuesIdList.Contains(a.VenuesId));
            }
            #endregion

            #region 场地名称-模糊查询

            var siteName = input.SiteName;
            if (!string.IsNullOrWhiteSpace(siteName))
            {
                data = data.Where(a => a.SiteName.Contains(siteName));
            }
            #endregion

            #region 场地编码-模糊查询

            var siteCode = input.SiteCode;
            if (!string.IsNullOrWhiteSpace(siteCode))
            {
                data = data.Where(a => a.SiteCode.Contains(siteCode));
            }

            #endregion  

            #region 场地类型
            var siteTypIdList = input.SiteTypIdList;
            if (siteTypIdList != null && siteTypIdList.Count > 0)
            {
                data = data.Where(a => siteTypIdList.Contains(a.SiteTypeId));
            }

            #endregion

            #region 是否开启现在预订

            var enableOnlineOrder = input.EnableOnlineOrder;
            if (enableOnlineOrder != null && enableOnlineOrder.HasValue)
            {
                data = data.Where(a => a.EnableOnlineOrder == enableOnlineOrder.Value);

            }

            #endregion

            #region 停用、启用
            var status = input.Status;
            if (status != null && status.HasValue)
            {
                data = data.Where(a => a.Status == status.Value);

            }
            #endregion  

            return data;
        }

        /// <summary>
        /// 冗余字段赋值
        /// </summary>
        /// <returns></returns>
        private async Task SiteTypeMap(List<BasSiteBasicDto> input)
        {
            if (input.IsNullOrEmpty()) return;

            //机构、场馆、场地类型

            //机构
            var orgIds = input.Select(a => a.OrgId).Distinct().ToList();
            var orgData = await _sysOrgRep.AsQueryable().Where(a => a.IsDelete == false && orgIds.Contains(a.Id)).Select(a => new { a.Id, a.Name }).ToListAsync();

            //场馆       
            var venuesIds = input.Select(a => a.VenuesId).Distinct().ToList();
            var venuesList = _basVenuesRep.AsQueryable().Where(a => a.IsDelete == false && venuesIds.Contains(a.Id)).Select(a => new
            {
                a.Id,
                a.VenuesCode,
                a.VenuesName
            }).ToList();

            //场地类型
            var siteTypeIds = input.Select(a => a.SiteTypeId).Distinct().ToList();
            var basSiteTypeList = _basSiteTypeRep.AsQueryable().Where(a => a.IsDelete == false && siteTypeIds.Contains(a.Id)).Select(a => new
            {
                a.Id,
                a.SiteTypeName
            }).ToList();


            foreach (var item in input)
            {
                //机构名称
                if (orgData != null)
                {
                    var curOrg = orgData.FirstOrDefault(a => a.Id == item.OrgId);
                    if (curOrg != null) item.OrgName = curOrg.Name;
                }

                //场馆
                var curVenues = venuesList.FirstOrDefault(a => a.Id == item.VenuesId);
                if (curVenues != null) item.VenuesName = curVenues.VenuesName;

                //场地类型
                var curSiteType = basSiteTypeList.FirstOrDefault(a => a.Id == item.SiteTypeId);
                if (curSiteType != null) item.SiteTypeName = curSiteType.SiteTypeName;
            }

        }

        /// <summary>
        /// 参数为NULL验证
        /// </summary>
        /// <param name="input"></param>
        private void ParamNull(object input)
        {
            if (input == null) throw Oops.Oh("参数错误:参数为NULL");
        }

        #endregion

    }

}
